package domain

import (
	"context"
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/mars/pkg/errors"
)

// BookingStatus 预约状态枚举
type BookingStatus string

const (
	BookingStatusPending   BookingStatus = "pending"   // 待确认
	BookingStatusConfirmed BookingStatus = "confirmed" // 已确认
	BookingStatusCancelled BookingStatus = "cancelled" // 已取消
	BookingStatusRejected  BookingStatus = "rejected"  // 已拒绝
	BookingStatusCompleted BookingStatus = "completed" // 已完成
)

// VenueType 场地类型枚举
type VenueType string

const (
	VenueTypeFamilyFishing VenueType = "family_fishing" // 亲子垂钓
	VenueTypeLureFishing   VenueType = "lure_fishing"   // 路亚钓鱼
	VenueTypeForestYoga    VenueType = "forest_yoga"    // 森林瑜伽
)

// TimeSlot 时间段枚举
type TimeSlot string

const (
	TimeSlotMorning   TimeSlot = "morning"   // 上午段 (09:00-12:00)
	TimeSlotAfternoon TimeSlot = "afternoon" // 下午段 (14:00-17:00)
	TimeSlotFullDay   TimeSlot = "full_day"  // 全天段 (09:00-17:00)
)

// Booking 预约实体
type Booking struct {
	ID           string        `json:"_id,omitempty" bson:"_id,omitempty"`         // 预约ID
	BookingNo    string        `json:"bookingNo" bson:"bookingNo"`                 // 预约号
	OpenID       string        `json:"openid" bson:"openid"`                       // 用户openid
	VenueType    VenueType     `json:"venueType" bson:"venueType"`                 // 场地类型
	BookingDate  int64         `json:"bookingDate" bson:"bookingDate"`             // 预约日期 (秒级时间戳)
	TimeSlot     TimeSlot      `json:"timeSlot" bson:"timeSlot"`                   // 时间段
	TicketType   TicketType    `json:"ticketType" bson:"ticketType"`               // 入场券类型
	Status       BookingStatus `json:"status" bson:"status"`                       // 预约状态
	Remark       string        `json:"remark,omitempty" bson:"remark"`             // 备注
	CancelReason string        `json:"cancelReason,omitempty" bson:"cancelReason"` // 取消原因
	RejectReason string        `json:"rejectReason,omitempty" bson:"rejectReason"` // 拒绝原因
	CancelTime   *int64        `json:"cancelTime,omitempty" bson:"cancelTime"`     // 取消时间 (秒级时间戳)
	RejectTime   *int64        `json:"rejectTime,omitempty" bson:"rejectTime"`     // 拒绝时间 (秒级时间戳)
	CreateTime   int64         `json:"createTime" bson:"createTime"`               // 创建时间 (秒级时间戳)
	UpdateTime   int64         `json:"updateTime" bson:"updateTime"`               // 更新时间 (秒级时间戳)
	// 扩展字段 - 用于前端显示
	VenueName        string `json:"venueName,omitempty" bson:"-"`        // 场地名称
	VenueDescription string `json:"venueDescription,omitempty" bson:"-"` // 场地描述
	TimeSlotName     string `json:"timeSlotName,omitempty" bson:"-"`     // 时间段名称
	UserNickName     string `json:"userNickName,omitempty" bson:"-"`     // 用户昵称
	UserAvatarUrl    string `json:"userAvatarUrl,omitempty" bson:"-"`    // 用户头像
}

// BookingQueryParams 查询参数
type BookingQueryParams struct {
	OpenID      string        `json:"openid,omitempty"`
	Phone       string        `json:"phone,omitempty"`
	VenueType   VenueType     `json:"venueType,omitempty"`
	Status      BookingStatus `json:"status,omitempty"`
	BookingDate *int64        `json:"bookingDate,omitempty"` // 预约日期 (秒级时间戳)
	TimeSlot    TimeSlot      `json:"timeSlot,omitempty"`
	PaginationParams
	SortParams
}

// NewDefaultBookingQueryParams 创建默认预约查询参数
func NewDefaultBookingQueryParams() BookingQueryParams {
	return BookingQueryParams{
		PaginationParams: DefaultPaginationParams,
		SortParams:       DefaultSortParams,
	}
}

// BookingValidator 预约验证器
type BookingValidator struct {
	paginationValidator *PaginationValidator
	idValidator         *IDValidator
	dateValidator       *DateValidator
	sortValidator       *SortValidator
	venueTypeValidator  *EnumValidator
	statusValidator     *EnumValidator
	timeSlotValidator   *EnumValidator
	reasonValidator     *StringValidator
}

// NewBookingValidator 创建预约验证器
func NewBookingValidator() *BookingValidator {
	return &BookingValidator{
		paginationValidator: NewPaginationValidator(1000),
		idValidator:         NewIDValidator("booking ID", 2, 128),
		dateValidator:       NewDateValidator(),
		sortValidator:       NewSortValidator([]string{"createTime", "updateTime", "bookingDate", "status"}),
		venueTypeValidator: NewEnumValidator("venue type",
			[]string{string(VenueTypeFamilyFishing), string(VenueTypeLureFishing), string(VenueTypeForestYoga)}, false),
		statusValidator: NewEnumValidator("booking status",
			[]string{string(BookingStatusPending), string(BookingStatusConfirmed), string(BookingStatusCancelled),
				string(BookingStatusRejected), string(BookingStatusCompleted)}, false),
		timeSlotValidator: NewEnumValidator("time slot",
			[]string{string(TimeSlotMorning), string(TimeSlotAfternoon), string(TimeSlotFullDay)}, false),
		reasonValidator: NewStringValidator("reason", 500, true),
	}
}

// ValidateQueryParams 验证查询参数
func (bv *BookingValidator) ValidateQueryParams(cxt *gin.Context) (BookingQueryParams, error) {
	// 验证分页参数
	pagination, err := bv.paginationValidator.ValidateAndParse(cxt)
	if err != nil {
		return BookingQueryParams{}, err
	}

	// 验证排序参数
	sort, err := bv.sortValidator.ValidateAndParse(cxt)
	if err != nil {
		return BookingQueryParams{}, err
	}

	// 验证场地类型
	venueType := cxt.Query("venueType")
	if err := bv.venueTypeValidator.Validate(venueType); err != nil {
		return BookingQueryParams{}, err
	}

	// 验证预约状态
	status := cxt.Query("status")
	if err := bv.statusValidator.Validate(status); err != nil {
		return BookingQueryParams{}, err
	}

	// 验证时间段
	timeSlot := cxt.Query("timeSlot")
	if err := bv.timeSlotValidator.Validate(timeSlot); err != nil {
		return BookingQueryParams{}, err
	}

	// 验证预约日期
	bookingDate, err := bv.dateValidator.ValidateDate(cxt.Query("bookingDate"))
	if err != nil {
		return BookingQueryParams{}, err
	}

	return BookingQueryParams{
		OpenID:           cxt.Query("openid"),
		Phone:            cxt.Query("phone"),
		VenueType:        VenueType(venueType),
		Status:           BookingStatus(status),
		BookingDate:      bookingDate,
		TimeSlot:         TimeSlot(timeSlot),
		PaginationParams: pagination,
		SortParams:       sort,
	}, nil
}

// ValidateBookingID 验证预约ID
func (bv *BookingValidator) ValidateBookingID(cxt *gin.Context, paramName string) (string, error) {
	return bv.idValidator.ValidateFromParam(cxt, paramName)
}

// ValidateAvailableSlotParams 验证获取可用时间段的参数
func (bv *BookingValidator) ValidateAvailableSlotParams(cxt *gin.Context) (VenueType, int64, error) {
	// 验证场地类型
	venueTypeStr := cxt.Query("venueType")
	venueTypeValidator := NewEnumValidator("venue type",
		[]string{string(VenueTypeFamilyFishing), string(VenueTypeLureFishing), string(VenueTypeForestYoga)}, true)
	if err := venueTypeValidator.Validate(venueTypeStr); err != nil {
		return "", 0, err
	}

	// 验证预约日期
	bookingDate, err := bv.dateValidator.ValidateDateRequired(cxt.Query("bookingDate"))
	if err != nil {
		return "", 0, err
	}

	return VenueType(venueTypeStr), bookingDate, nil
}

// ValidateReason 验证原因参数
func (bv *BookingValidator) ValidateReason(reason string) error {
	return bv.reasonValidator.Validate(reason)
}

// ValidateBooking 验证预约实体
func (bv *BookingValidator) ValidateBooking(booking *Booking) error {
	if booking == nil {
		return errors.New(http.StatusBadRequest, "booking object is required")
	}

	// 验证必填字段
	if booking.OpenID == "" {
		return errors.New(http.StatusBadRequest, "openid is required")
	}

	if booking.VenueType == "" {
		return errors.New(http.StatusBadRequest, "venue type is required")
	}

	if err := bv.venueTypeValidator.Validate(string(booking.VenueType)); err != nil {
		return err
	}

	if booking.TimeSlot == "" {
		return errors.New(http.StatusBadRequest, "time slot is required")
	}

	if err := bv.timeSlotValidator.Validate(string(booking.TimeSlot)); err != nil {
		return err
	}

	if booking.BookingDate == 0 {
		return errors.New(http.StatusBadRequest, "booking date is required")
	}

	// 验证备注长度
	if booking.Remark != "" && len(booking.Remark) > 500 {
		return errors.New(http.StatusBadRequest, "remark length must not exceed 500 characters")
	}

	return nil
}

// BookingStats 预约统计信息
type BookingStats struct {
	Total         int64 `json:"total"`         // 总预约数
	Pending       int64 `json:"pending"`       // 待确认
	Confirmed     int64 `json:"confirmed"`     // 已确认
	Cancelled     int64 `json:"cancelled"`     // 已取消
	Rejected      int64 `json:"rejected"`      // 已拒绝
	Completed     int64 `json:"completed"`     // 已完成
	FamilyFishing int64 `json:"familyFishing"` // 亲子垂钓
	LureFishing   int64 `json:"lureFishing"`   // 路亚钓鱼
	ForestYoga    int64 `json:"forestYoga"`    // 森林瑜伽
}

// VenueCapacity 场地容量配置
type VenueCapacity struct {
	VenueType VenueType `json:"venueType"`
	Capacity  int       `json:"capacity"`
}

// TimeSlotAvailability 时间段可用性
type TimeSlotAvailability struct {
	TimeSlot  TimeSlot `json:"timeSlot"`
	Available bool     `json:"available"`
	Remaining int      `json:"remaining"`
	TimeRange string   `json:"timeRange"`
}

// AvailableSlots 可用时间段信息
type AvailableSlots struct {
	VenueType      VenueType                       `json:"venueType"`
	BookingDate    string                          `json:"bookingDate"`
	Capacity       int                             `json:"capacity"`
	AvailableSlots map[string]TimeSlotAvailability `json:"availableSlots"`
}

// BookingGateway 预约网关接口
type BookingGateway interface {
	// GetBookingList 获取预约列表
	GetBookingList(ctx context.Context, params BookingQueryParams) ([]Booking, int64, error)

	// GetBooking 根据ID获取预约详情
	GetBooking(ctx context.Context, bookingID string) (*Booking, error)

	// GetBookingByNo 根据预约号获取预约详情
	GetBookingByNo(ctx context.Context, bookingNo string) (*Booking, error)

	// CreateBooking 创建预约
	CreateBooking(ctx context.Context, booking *Booking) error

	// UpdateBooking 更新预约信息
	UpdateBooking(ctx context.Context, bookingID string, booking *Booking) error

	// UpdateBookingStatus 更新预约状态
	UpdateBookingStatus(ctx context.Context, bookingID string, status BookingStatus, oldStatus BookingStatus, rejectReason string) (int, error)

	// ConfirmBooking 确认预约
	ConfirmBooking(ctx context.Context, bookingID string) error

	// RejectBooking 拒绝预约
	RejectBooking(ctx context.Context, bookingID string, reason string) error

	// CancelBooking 取消预约
	CancelBooking(ctx context.Context, bookingID string, reason string) error

	// GetBookingStats 获取预约统计信息
	GetBookingStats(ctx context.Context) (*BookingStats, error)

	// CheckTimeSlotConflict 检查时间段冲突
	CheckTimeSlotConflict(ctx context.Context, openid string, bookingDate int64, timeSlot TimeSlot) (bool, error)

	// CheckVenueCapacity 检查场地容量
	CheckVenueCapacity(ctx context.Context, venueType VenueType, bookingDate int64, timeSlot TimeSlot) (bool, int, error)

	// GetAvailableTimeSlots 获取可用时间段
	GetAvailableTimeSlots(ctx context.Context, venueType VenueType, bookingDate int64) (*AvailableSlots, error)

	// ValidateTicketPurchase 验证入场券购买情况
	ValidateTicketPurchase(ctx context.Context, openid string, venueType VenueType) error
}

// GetVenueName 获取场地名称
func (v VenueType) GetVenueName() string {
	switch v {
	case VenueTypeFamilyFishing:
		return "亲子垂钓"
	case VenueTypeLureFishing:
		return "路亚钓鱼"
	case VenueTypeForestYoga:
		return "森林瑜伽"
	default:
		return string(v)
	}
}

// GetVenueDescription 获取场地描述
func (v VenueType) GetVenueDescription() string {
	switch v {
	case VenueTypeFamilyFishing:
		return "适合亲子活动的垂钓场地"
	case VenueTypeLureFishing:
		return "专业路亚钓鱼场地"
	case VenueTypeForestYoga:
		return "在森林中进行瑜伽练习"
	default:
		return ""
	}
}

// GetTimeSlotName 获取时间段名称
func (t TimeSlot) GetTimeSlotName() string {
	switch t {
	case TimeSlotMorning:
		return "上午段 (09:00-12:00)"
	case TimeSlotAfternoon:
		return "下午段 (14:00-17:00)"
	case TimeSlotFullDay:
		return "全天段 (09:00-17:00)"
	default:
		return string(t)
	}
}

// GetTimeRange 获取时间范围
func (t TimeSlot) GetTimeRange() string {
	switch t {
	case TimeSlotMorning:
		return "09:00-12:00"
	case TimeSlotAfternoon:
		return "14:00-17:00"
	case TimeSlotFullDay:
		return "09:00-17:00"
	default:
		return ""
	}
}

// GetStatusText 获取状态文本
func (s BookingStatus) GetStatusText() string {
	switch s {
	case BookingStatusPending:
		return "待确认"
	case BookingStatusConfirmed:
		return "已确认"
	case BookingStatusCancelled:
		return "已取消"
	case BookingStatusRejected:
		return "已拒绝"
	case BookingStatusCompleted:
		return "已完成"
	default:
		return string(s)
	}
}

// GetRequiredTicketType 根据场地类型获取所需入场券类型
func GetRequiredTicketType(venueType VenueType) TicketType {
	switch venueType {
	case VenueTypeFamilyFishing:
		return TicketTypeFamilyFishing
	case VenueTypeLureFishing:
		return TicketTypeLureFishing
	case VenueTypeForestYoga:
		return TicketTypeForestYoga
	default:
		return ""
	}
}

// GetVenueCapacity 获取场地容量配置
func GetVenueCapacity(venueType VenueType) int {
	capacityMap := map[VenueType]int{
		VenueTypeFamilyFishing: 10, // 亲子垂钓容量10
		VenueTypeLureFishing:   8,  // 路亚钓鱼容量8
		VenueTypeForestYoga:    15, // 森林瑜伽容量15
	}
	if capacity, exists := capacityMap[venueType]; exists {
		return capacity
	}
	return 10 // 默认容量
}

// IsValidStatus 检查状态是否有效
func IsValidStatus(status string) bool {
	validStatuses := map[string]bool{
		string(BookingStatusPending):   true,
		string(BookingStatusConfirmed): true,
		string(BookingStatusCancelled): true,
		string(BookingStatusRejected):  true,
		string(BookingStatusCompleted): true,
	}
	return validStatuses[status]
}

// IsValidVenueType 检查场地类型是否有效
func IsValidVenueType(venueType string) bool {
	validTypes := map[string]bool{
		string(VenueTypeFamilyFishing): true,
		string(VenueTypeLureFishing):   true,
		string(VenueTypeForestYoga):    true,
	}
	return validTypes[venueType]
}

// IsValidTimeSlot 检查时间段是否有效
func IsValidTimeSlot(timeSlot string) bool {
	validSlots := map[string]bool{
		string(TimeSlotMorning):   true,
		string(TimeSlotAfternoon): true,
		string(TimeSlotFullDay):   true,
	}
	return validSlots[timeSlot]
}
